package com.ls.rabbitmqService;

import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * rabbitmq channel pool
 */
public class RabbitmqChannelPool {

    static Logger logger = LoggerFactory.getLogger(RabbitmqChannelPool.class);

    //每个tcp连接上开辟的信道channel最大数
    public static int maxTcpChannelNum=4;

    public static final class RabbitmqChannel {
        private Channel channel;
        private RabbitmqConnectionPool.RabbitmqConnection connection;

        public RabbitmqChannel(Channel channel, RabbitmqConnectionPool.RabbitmqConnection connection) {
            this.channel = channel;
            this.connection = connection;
            connection.incrNewChannelNum();
        }

        public Channel getChannel() {
            return channel;
        }

        public void setChannel(Channel channel) {
            this.channel = channel;
        }

        public RabbitmqConnectionPool.RabbitmqConnection getConnection() {
            return connection;
        }

        public void setConnection(RabbitmqConnectionPool.RabbitmqConnection connection) {
            this.connection = connection;
        }
        public void close(){
            if(channel!=null){
                try {
                    channel.close();
                    connection.decrNewChannelNum();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (TimeoutException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static synchronized RabbitmqChannel getChannel(int...counts){
        RabbitmqChannel channel=null;
        RabbitmqConnectionPool.RabbitmqConnection connection = RabbitmqConnectionPool.getConnection();
        if(connection!=null && connection.getConnection()!=null){
                try {
                    //如果tcp连接的channel数量超过我们的预期了，那就不处理了返回null即可 估计不太可能除非大流量并发时间较长 重试4次
                    if (connection.getNewChannelNum() >= maxTcpChannelNum || connection.getNewChannelNum() >= connection.getConnection().getChannelMax()) {
                        if(counts!=null && counts.length>0){
                            //不作处理了,等待10毫秒还没有
                            if(counts[0]<=3){
                                int count=counts[0];
                                channel=getChannel(++count);
                            }
                        }else{
                            try {
                                TimeUnit.MILLISECONDS.sleep(10);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            channel=getChannel(1);
                        }
                        if(channel==null)
                            logger.warn(String.format("tcp连接上的channel超出我们的预期了channelNum:%d,tcpId:%d,count:%d", connection.getNewChannelNum(), connection.getConnection().getId(),counts!=null && counts.length>0?counts[0]:0));
                        return channel;
                    }
                    channel = new RabbitmqChannel(connection.getConnection().createChannel(), connection);
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
        if(counts!=null && counts.length>0 && channel!=null){
            //logger.warn(String.format("tcp连接上的重试成功的channelNum:%d,tcpId:%d,count:%d", connection.getNewChannelNum(), connection.getConnection().getId(),counts!=null && counts.length>0?counts[0]:0));
        }
        return channel;
    }

}
